home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / dviware / umddvi / dev / ip.c < prev    next >
C/C++ Source or Header  |  1990-10-01  |  18KB  |  697 lines

  1. /*
  2.  * Copyright (c) 1987 University of Maryland Department of Computer Science.
  3.  * All rights reserved.  Permission to copy for any purpose is hereby granted
  4.  * so long as this copyright notice remains intact.
  5.  */
  6.  
  7. #ifndef lint
  8. static char rcsid[] = "$Header$";
  9. #endif
  10.  
  11. /*
  12.  * DVI to Interpress driver
  13.  *
  14.  * Reads DVI version 2 files and converts to Xerox Interpress format.
  15.  */
  16.  
  17. #include "types.h"
  18. #include "dvi.h"
  19. #include "dviclass.h"
  20. #include "dvicodes.h"
  21. #include "fio.h"
  22. #include "pxl.h"
  23. #include "search.h"
  24. #include "interpress.h"
  25. #include <stdio.h>
  26.  
  27. char  *ProgName;
  28. extern int   errno;
  29. extern char *optarg;
  30. extern int   optind;
  31.  
  32. /* Globals */
  33. char    serrbuf[BUFSIZ];    /* buffer for stderr */
  34.  
  35. /* DVI style arithmetic:  when moving horizontally by a DVI distance >=
  36.    ``space'', we are to recompute horizontal position from DVI units;
  37.    otherwise, we are to use device resolution units to keep track of
  38.    horizontal position.  A similar scheme must be used for vertical
  39.    positioning. */
  40. struct fontinfo {
  41.     struct pxltail *px;        /* pxl file info */
  42.     int     ipfont;        /* Interpress font index */
  43.     i32     pspace;        /* boundary between ``small'' & ``large''
  44.                    spaces (for positive horizontal motion) */
  45.     i32     nspace;        /* -4 * pspace, for negative motion */
  46.     i32     vspace;        /* 5 * pspace, for vertical motion */
  47.     int     cwidth[128];    /* width (in DEVs) of each char */
  48.     char    cload[128];        /* flag for ``char loaded into Imagen'' */
  49. };
  50.  
  51. int     MaxDrift;        /* the maximum allowable difference between
  52.                    hh and SPtoDEV(dvi_h), and vv and.... */
  53.  
  54. struct search *FontFinder;    /* search table for DVI index => fontinfo */
  55. struct fontinfo *CurrentFont;    /* the current font (if any) */
  56. int    NextIPFont;        /* during font definition, the next ip font
  57.                    index */
  58. int    FontErrors;        /* true => error(s) during font definition */
  59.  
  60. char   *TeXfonts;        /* getenv("TEXFONTS") */
  61.  
  62. int     ExpectBOP;        /* true => BOP ok */
  63. int     ExpectEOP;        /* true => EOP ok */
  64.  
  65. int    DPI;            /* -d => device resolution (dots/inch) */
  66. /* int  LFlag;            /* -l => landscape mode (eventually...) */
  67. int     SFlag;            /* -s => silent (no page #s) */
  68. int     XFlag;            /* -x => debug (undocumented) */
  69.  
  70. int     hh;            /* current horizontal position, in DEVs */
  71. int     vv;            /* current vertical position, in DEVs */
  72.  
  73. /* Similar to dvi_stack, but includes ``hh'' and ``vv'', which are usually
  74.    but not always the same as SPtoDEV(h) and SPtoDEV(v): */
  75. struct localstack {
  76.     int     stack_hh;
  77.     int     stack_vv;
  78.     struct dvi_stack    stack_dvi;
  79. };
  80.  
  81. struct localstack  *dvi_stack;    /* base of stack */
  82. struct localstack  *dvi_stackp;    /* current place in stack */
  83.  
  84. int    HHMargin;        /* horizontal margin (in DEVs) */
  85. int    VVMargin;        /* vertical margin (in DEVs) */
  86.  
  87. int    Numerator;        /* numerator from DVI file */
  88. int    Denominator;        /* denominator from DVI file */
  89. int    DVIMag;            /* magnification from DVI file */
  90.  
  91. double    UserMag;        /* user specified magnification */
  92. double    GlobalMag;        /* overall magnification (UserMag*DVIMag) */
  93. double    conv;            /* conversion factor for magnified DVI units */
  94.  
  95. double    OneHalf = 0.5;        /* .5, so compiler can generate constant only
  96.                    once */
  97. double    Zero = 0.0;        /* likewise */
  98. double    _d_;            /* Used to store intermediate results.  The
  99.                    compiler should do this for us, but it's
  100.                    too stupid. */
  101.  
  102. int    IpHH;            /* Interpress horizontal position */
  103. int    IpVV;            /* Interpress vertical position */
  104. int    IpFont;            /* Interpress current-font number */
  105.  
  106. char *getenv (), *malloc ();
  107.  
  108. /* Absolute value */
  109. #define ABS(n) ((n) >= 0 ? (n) : -(n))
  110.  
  111. /* Round a floating point number to integer */
  112. #define ROUND(f) ((int) (_d_ = (f), \
  113.              _d_ < Zero ? _d_ - OneHalf : _d_ + OneHalf)
  114.  
  115. /* Convert to floating point */
  116. #define FLOAT(i) ((double) (i))
  117.  
  118. /* Convert a value in sp's to dev's, and vice versa */
  119. #define SPtoDEV(sp)  (ROUND ((sp)  * conv))
  120. #define DEVtoSP(dev) (ROUND ((dev) / conv))
  121.  
  122. /* Put a two-byte (word) value */
  123. #define putword(w) (putchar ((w) >> 8), putchar (w))
  124.  
  125. /* Correct devpos (the virtual device position) to be within MaxDrift pixels
  126.    of dvipos (the virtual DVI position). */
  127. #define    FIXDRIFT(devpos, dvipos) \
  128.     if (ABS ((devpos) - (dvipos)) <= MaxDrift); \
  129.     else \
  130.         if ((devpos) < (dvipos)) \
  131.         (devpos) = (dvipos) - MaxDrift; \
  132.         else \
  133.         (devpos) = (dvipos) + MaxDrift
  134.  
  135. /* Compute the DEV widths of the characters in the given font */
  136. ComputeCWidths (fi)
  137. struct fontinfo *fi;
  138. {
  139.     register int    i;
  140.     register struct chinfo *ch;
  141.     register int   *cw;
  142.  
  143.     ch = fi -> px -> px_info;
  144.     cw = fi -> cwidth;
  145.     i = 128;
  146.     while (--i >= 0) {
  147.     *cw++ = SPtoDEV (ch -> ch_TFMwidth);
  148.     ch++;
  149.     }
  150. }
  151.  
  152. SelectFont (n)
  153. int n;
  154. {
  155.     register struct fontinfo *f;
  156.  
  157.     CurrentFont = f = FindFont ((i32) n, (struct fontinfo *) 0);
  158.     CurrentFontIndex = f - FontInfo;
  159. }
  160.  
  161. /* Start a page (process a DVI_BOP) */
  162. /* NOTE: I'm depending on getting a BOP before any characters or rules on a
  163.    page! */
  164. BeginPage () {
  165.     register int   *i;
  166.     static int  count[10];    /* the 10 counters */
  167.     static int  beenhere;
  168.  
  169.     if (!ExpectBOP)
  170.     error (1, 0, "unexpected BOP");
  171.     if (beenhere) {
  172.     if (!SFlag)
  173.         putc (' ', stderr);
  174.     }
  175.     else
  176.     beenhere++;
  177.  
  178.     dvi_stackp = dvi_stack;
  179.  
  180.     ExpectBOP = 0;
  181.     ExpectEOP++;        /* set the new "expect" state */
  182.  
  183.     for (i = count; i < &count[sizeof count / sizeof *count]; i++)
  184.     fGetLong (stdin, *i);
  185.     fGetLong (stdin, i);    /* previous page pointer */
  186.  
  187.     if (!SFlag) {
  188.     fprintf (stderr, "[%d", count[0]);
  189.     (void) fflush (stderr);
  190.     }
  191.  
  192.     putchar (imP_Page);        /* XXX */
  193.     IpHH = 0;
  194.     IpVV = 0;
  195.  
  196.     hh = HHMargin;
  197.     vv = VVMargin;
  198.     dvi_h = DEVtoSP (hh);
  199.     dvi_v = DEVtoSP (vv);
  200.     dvi_w = 0;
  201.     dvi_x = 0;
  202.     dvi_y = 0;
  203.     dvi_z = 0;
  204. }
  205.  
  206. /* End a page (process a DVI_EOP) */
  207. EndPage () {
  208.     if (!ExpectEOP)
  209.     error (1, 0, "unexpected EOP");
  210.  
  211.     if (!SFlag) {
  212.     putc (']', stderr);
  213.     (void) fflush (stderr);
  214.     }
  215.  
  216.     ExpectEOP = 0;
  217.     ExpectBOP++;
  218.  
  219.     putchar (imP_EndPage);    /* XXX */
  220. }
  221.  
  222. /* Begin XXX */
  223. /* Store the relevant information from the DVI postamble, and set up
  224.    various internal things. */
  225. PosotAmbleHeader (p)
  226. register struct PostAmbleInfo *p; {
  227.     register int n;
  228.  
  229.     PrevPagePointer = p -> pai_PrevPagePointer;
  230.     Numerator = p -> pai_Numerator;
  231.     Denominator = p -> pai_Denominator;
  232.     DVIMag = p -> pai_DVIMag;
  233.  
  234.  /* Here we sneakily correct for the actual device resolution, so that we can
  235.     pretend that it's 200 dots per inch. */
  236.     UserMag *= FLOAT (DPI) / 200.0;
  237.  
  238.     GlobalMag = DMagFactor (DVIMag) * UserMag;
  239.  
  240.  /* The conversion factor is figured as follows:  there are exactly n/d DVI
  241.     units per decimicron, and 254000 decimicrons per inch, and 200 pixels per
  242.     inch.  Then we have to adjust this by the stated magnification. */
  243.     conv = (Numerator / 254000.0) * (200.0 / Denominator) * GlobalMag;
  244.  
  245.     n = p -> pai_DVIStackSize * sizeof *dvi_stack;
  246.     dvi_stack = (struct localstack *) malloc ((unsigned) n);
  247.     if ((dvi_stackp = dvi_stack) == 0)
  248.     error (1, errno, "can't allocate %d DVI stack bytes", n);
  249.     IntGlobalMag = ROUND (GlobalMag * 1000.0);
  250. }
  251.  
  252. /* Handle one of the font definitions from the DVI postamble. */
  253. PostAmbleFontDef (p)
  254. register struct PostAmbleFont *p; {
  255.     register struct fontinfo *f;
  256.     register char *s;
  257.     int def = S_CREATE | S_EXCL;
  258.  
  259.     f = (struct fontinfo *) SSearch (FontFinder, p -> paf_DVIFontIndex, &def);
  260.     if (f == 0)
  261.     if (def & S_COLL)
  262.         error (1, 0, "font %d already defined", p -> paf_DVIFontIndex);
  263.     else
  264.         error (1, 0, "can't stash font %d (out of memory?)",
  265.             p -> paf_DVIFontIndex);
  266.  
  267.     f -> ipfont = NextIPFont++;
  268.     s = GenPXLFileName (p -> paf_name, p -> paf_DVIMag,
  269.         p -> paf_DVIDesignSize, IntGlobalMag, TeXfonts);
  270.     if ((f -> px = ReadPXLFile (s, 1)) == 0) {
  271.     error (0, errno, "can't find font \"%s\"", s);
  272.     FontErrors++;
  273.     return;
  274.     }
  275.     if (p -> paf_DVIChecksum != f -> px -> px_checksum)
  276.         error (0, 0, "\
  277. WARNING: width tables and raster tables have different\n\
  278. \tchecksums for font \"%s\"\n\
  279. \tPlease notify your TeX maintainer\n\
  280. \t(TFM checksum = 0%o, PXL checksum = 0%o)",
  281.             s, dvi_checksum, f -> px -> px_checksum);
  282.  
  283.     ScaleTFMWidths (f -> px, dvi_mag);
  284.     ComputeCWidths (f);
  285.     f -> pspace = p -> paf_DVIMag / 6;    /* a three-unit ``thin space'' */
  286.     f -> nspace = -4 * f -> pspace;
  287.     f -> vspace = 5 * f -> pspace;
  288. }
  289.  
  290. /* Read the postamble. */
  291. ReadPostAmble () {
  292.     static char s[2] = { 's', 0 };
  293.  
  294.     if ((FontFinder = SCreate (sizeof (struct fontinfo))) == 0)
  295.     error (1, 0, "can't create FontFinder (out of memory?)");
  296.     ScanPostAmble (stdin, PostAmbleHeader, PostAmbleFontDef);
  297.     if (FontErrors)
  298.     error (1, 0, "missing font%s prevent%s output (sorry)",
  299.         FontErrors > 1 ? s : &s[1], FontErrors == 1 ? s : &s[1]);
  300. }
  301. /* End XXX */
  302.  
  303. /* Read the preamble and do a few sanity checks */
  304. ReadPreAmble () {
  305.     register int   n;
  306.  
  307.     rewind (stdin);
  308.     if (GetByte (stdin) != Sign8 (DVI_PRE))
  309.     error (1, 0, "missing PRE");
  310.     if (GetByte (stdin) != Sign8 (DVI_VERSION))
  311.     error (1, 0, "mismatched version numbers");
  312.     if (GetLong (stdin) != Numerator)
  313.     error (1, 0, "mismatched numerator");
  314.     if (GetLong (stdin) != Denominator)
  315.     error (1, 0, "mismatched denominator");
  316.     if (GetLong (stdin) != DVIMag)
  317.     error (1, 0, "mismatched \\magfactor");
  318.     n = UnSign8 (GetByte (stdin));
  319.     while (--n >= 0)
  320.     (void) GetByte (stdin);
  321. }
  322.  
  323. main (argc, argv)
  324. int argc;
  325. register char **argv;
  326. {
  327.     register int    c;
  328.     char   *inname;
  329.  
  330.     setbuf (stderr, serrbuf);
  331.  
  332.     ProgName = *argv;
  333.     UserMag = 1.0;
  334.     MaxDrift = DefaultMaxDrift;
  335.     DPI = DefaultDPI;
  336.     inname = "stdin";
  337.  
  338.     while ((c = getopt (argc, argv, "d:m:r:s")) != EOF) {
  339.     switch (c) {
  340.         case 'd':        /* max drift value */
  341.         MaxDrift = atoi (optarg);
  342.         break;
  343. /*        case 'l':        /* landscape mode */
  344. /*        LFlag++; */
  345. /*        break; */
  346.         case 'm':        /* magnification */
  347.         UserMag = DMagFactor (atoi (optarg));
  348.         break;
  349.         case 'r':        /* resolution */
  350.         DPI = atoi (optarg);
  351.         break;
  352.         case 's':        /* silent */
  353.         SFlag++;
  354.         break;
  355.         case 'x':        /* enable debugging */
  356.         XFlag++;
  357.         break;
  358.         case '?':
  359.         fprintf (stderr, "\
  360. Usage: %s [-d drift] [-m mag] [-s] [-r resolution] [file]\n",
  361.             ProgName);
  362.         (void) fflush (stderr);
  363.         exit (1);
  364.     }
  365.     }
  366.     if (optind < argc)
  367.     if (freopen (inname = argv[optind], "r", stdin) == NULL)
  368.         error (1, errno, "can't open %s", inname);
  369.  
  370.  /* ReadPostAmble does an fseek which, if performed on a tty, tends to make
  371.     the shell log one out, thus the following kludge: */
  372.     if (isatty (fileno (stdin)))
  373.     error (1, 0, "input from ttys is expressly forbidden!");
  374.  
  375.     TeXfonts = getenv ("TEXFONTS");
  376.     if (TeXfonts == 0)
  377.     TeXfonts = "";
  378.  
  379.     ReadPostAmble ();
  380.  
  381.  /* Margins -- needs work! */
  382.     HHMargin = DefaultLeftMargin;/* XXX */
  383.     VVMargin = DefaultTopMargin;/* XXX */
  384.  
  385.     ReadPreAmble ();
  386.     ExpectBOP++;
  387.     (void) fseek (stdin, PrevPagePointer, 0);
  388.  
  389.  /* All set! */
  390.     printf ("Interpress/Xerox/2.1 ");
  391.     PutInstructionsBody (inname);
  392.     PutPreamble ();
  393.     ReadDVIFile ();
  394.  /* EOF is implicit (?) */
  395.  
  396.     exit (0);
  397. }
  398.  
  399. /* Skip a font definition (since we are using those from the postamble) */
  400. /* ARGSUSED */
  401. SkipFontDef (font)
  402. int font;
  403. {
  404.     register int i;
  405.  
  406.     (void) GetLong (stdin);
  407.     (void) GetLong (stdin);
  408.     (void) GetLong (stdin);
  409.     i = UnSign8 (GetByte (stdin)) + UnSign8 (GetByte (stdin));
  410.     while (--i >= 0)
  411.     (void) GetByte (stdin);
  412. }
  413.  
  414. /* Perform a \special - right now ignore all of them */
  415. DoSpecial (len)
  416. int len;            /* length of the \special string */
  417. {
  418.     error (0, 0, "warning: ignoring \\special");
  419.     (void) fseek (stdin, (long) len, 1);
  420. }
  421.  
  422. /* Draw a rule at the current (hh,vv) position.  There are two 4 byte
  423.    parameters.  The first is the height of the rule, and the second is the
  424.    width.  (hh,vv) is the lower left corner of the rule. */
  425. SetRule (advance)
  426. int advance;
  427. {
  428.     i32     rwidth,        /* rule width from DVI file */
  429.         rheight;        /* rule height from DVI file */
  430.     register int    h,
  431.             w;
  432.  
  433.     fGetLong (stdin, rheight);
  434.     fGetLong (stdin, rwidth);
  435.  
  436.  /* Rule sizes must be computed in this manner: */
  437.     h = conv * rheight;
  438.     if (FLOAT (h) < (conv * rheight))
  439.     h++;
  440.     w = conv * rwidth;
  441.     if (FLOAT (w) < (conv * rwidth))
  442.     w++;
  443.  
  444.  /* put the rule out */
  445.     if (IpHH != hh || IpVV != vv)
  446.     SetPosition (hh, vv);
  447.     putchar (imP_Rule);        /* XXX */
  448.     putword (w);        /* XXX */
  449.     putword (h);        /* XXX */
  450.     putword (-h + 1);        /* XXX */
  451.     if (advance) {
  452.     hh += w;
  453.     dvi_h += rwidth;
  454.     if (ABS (hh - (w = SPtoDEV (dvi_h))) > MaxDrift)
  455.         hh = w + (hh < w ? -MaxDrift : MaxDrift);
  456.     }
  457. }
  458.  
  459. /* FIXME (kerns, etc, etc) */
  460. /* resume XXX */
  461. /* This rather large routine reads the DVI file and calls on other routines
  462.    to do anything moderately difficult (except put characters:  there is
  463.    a bunch of ugly code with ``goto''s which makes things much faster) */
  464. ReadDVIFile () {
  465.     register int    c,
  466.             p;
  467.     int    advance;
  468.  
  469.     IpFamily = -1;
  470.  
  471.  /* Only way out is via "return" statement */
  472.     for (;;) {
  473.     /* Get the DVI byte, and if it's a character, put it */
  474. /*    c = UnSign8 (getchar ());  */
  475.     c = getchar ();        /* getchar() returns unsigned values */
  476.  
  477.     if (DVI_IsChar (c)) {    /* I know, ugly, but ... no function call
  478.                    overhead this way */
  479.         register struct chinfo *ch;
  480.         register struct fontinfo *cf;
  481.  
  482. set:
  483.         advance = 1;
  484. put:
  485.         cf = CurrentFont;
  486.         ch = &cf -> px -> px_info[c];
  487.         if (ch -> ch_width == 0)
  488.         goto ignore;    /* not a real character, just advance */
  489.     /* BEGIN INLINE EXPANSION OF IpSetPosition (the things we do in
  490.        the name of efficency! ;-) ) */
  491.         if (ImHH != hh) {
  492.         if (ImHH == hh - 1)
  493.             putchar (imP_Forw);
  494.         else if (ImHH == hh + 1)
  495.             putchar (imP_Backw);
  496.         else {
  497.             putchar (imP_SetHAbs);
  498.             putword (hh);
  499.         }
  500.         ImHH = hh;
  501.         }
  502.         if (ImVV != vv) {
  503.         putchar (imP_SetVAbs);
  504.         putword (vv);
  505.         ImVV = vv;
  506.         }
  507.     /* END INLINE EXPANSION OF ImSetPosition */
  508.         if (ImFamily != CurrentFontIndex) {
  509.         putchar (imP_SetFamily);
  510.         putchar (CurrentFontIndex);
  511.         ImFamily = CurrentFontIndex;
  512.         }
  513.         putchar (c);
  514.         ImHH += cf -> cwidth[c];
  515. ignore:
  516.         if (advance) {
  517. #ifdef DEBUG
  518.         if (XFlag) {
  519.             fprintf (stderr, "setchar%d h:=%d+%d=%d, hh:=%d\n",
  520.             c, dvi_h - DEVtoSP (HHMargin), ch->ch_TFMwidth,
  521.             dvi_h - DEVtoSP (HHMargin) + ch->ch_TFMwidth,
  522.             hh + CurrentFont->cwidth[c] - HHMargin);
  523.             fflush (stderr);
  524.         }
  525. #endif DEBUG
  526.         hh += cf -> cwidth[c];
  527.         dvi_h += ch -> ch_TFMwidth;
  528.         p = SPtoDEV (dvi_h);
  529.         FIXDRIFT (hh, p);
  530.         }
  531.         continue;
  532.     }
  533.     /* Wasn't a character, maybe a font? */
  534.     if (DVI_IsFont (c)) {
  535.         SelectFont ((i32) (c - DVI_FNTNUM0));
  536.         continue;
  537.     }
  538.     /* Wasn't a font, see if it's a generic one */
  539.     if (p = DVI_OpLen (c)) {
  540.     /* It's generic, get its parameter */
  541.         switch (p) {
  542.         case 1:
  543.             p = Sign8 (getchar ());
  544.             break;
  545.         case 2:
  546.             fGetWord (stdin, p);
  547.             p = Sign16 (p);
  548.             break;
  549.         case 3:
  550.             fGet3Byte (stdin, p);
  551.             p = Sign24 (p);
  552.             break;
  553.         case 4:
  554.             fGetLong (stdin, p);
  555.             break;
  556.         case 5:
  557.             p = UnSign8 (getchar ());
  558.             break;
  559.         case 6:
  560.             fGetWord (stdin, p);
  561.             p = UnSign16 (p);
  562.             break;
  563.         case 7:
  564.             fGet3Byte (stdin, p);
  565.             p = UnSign24 (p);
  566.             break;
  567.         }
  568.     /* Now that we have the parameter, perform the command */
  569.         switch (DVI_DT (c)) {
  570.         case DT_SET:
  571.             c = p;
  572.             goto set;
  573.         case DT_PUT:
  574.             c = p;
  575.             advance = 0;
  576.             goto put;
  577.         case DT_RIGHT:
  578. move_right:
  579.             dvi_h += p;
  580.         /* DVItype tells us that we must round motions in this way:
  581.            ``When the horizontal motion is small, like a kern, hh
  582.            changes by rounding the kern; but when the motion is
  583.            large, hh changes by rounding the true position so that
  584.            accumulated rounding errors disappear.'' */
  585.             if (p >= CurrentFont -> pspace ||
  586.                 p <= CurrentFont -> nspace)
  587.             hh = SPtoDEV (dvi_h);
  588.             else {
  589.             hh += SPtoDEV (p);
  590.             p = SPtoDEV (dvi_h);
  591.             FIXDRIFT (hh, p);
  592.             }
  593.             break;
  594.         case DT_W:
  595.             dvi_w = p;
  596.             goto move_right;
  597.         case DT_X:
  598.             dvi_x = p;
  599.             goto move_right;
  600.         case DT_DOWN:
  601. move_down:
  602.             dvi_v += p;
  603.         /* ``Vertical motion is done similarly, but with the
  604.            threshold between ``small'' and ``large'' increased by a
  605.            factor of 5.  The idea is to make fractions like $1\over2$
  606.            round consistently, but to absorb accumulated rounding
  607.            errors in the baeline-skip moves.'' */
  608.             if (ABS (p) >= CurrentFont -> vspace)
  609.             vv = SPtoDEV (dvi_v);
  610.             else {
  611.             vv += SPtoDEV (p);
  612.             p = SPtoDEV (dvi_v);
  613.             FIXDRIFT (vv, p);
  614.             }
  615.             break;
  616.         case DT_Y:
  617.             dvi_y = p;
  618.             goto move_down;
  619.         case DT_Z:
  620.             dvi_z = p;
  621.             goto move_down;
  622.         case DT_FNT:
  623.             SelectFont (p);
  624.             break;
  625.         case DT_XXX:
  626.             DoSpecial (p);
  627.             break;
  628.         case DT_FNTDEF:
  629.             SkipFontDef (p);
  630.             break;
  631. #ifdef PARANOID
  632.         default:
  633.             error (1, 0, "bad DVI_DT(%d): (%d)", c, DVI_DT (c));
  634. #endif PARANOID
  635.         }
  636.         continue;
  637.     }
  638.     /* Wasn't a char, wasn't a generic command, just pick it out from the
  639.        whole mess */
  640.     switch (c) {
  641.         case DVI_SETRULE:
  642.         SetRule (1);
  643.         break;
  644.         case DVI_PUTRULE:
  645.         SetRule (0);
  646.         break;
  647.         case DVI_NOP:
  648.         break;
  649.         case DVI_BOP:
  650.         BeginPage ();
  651.         break;
  652.         case DVI_EOP:
  653.         EndPage ();
  654.         if (PrevPagePointer == -1) {
  655.             if (!SFlag) {
  656.             fprintf (stderr, "\n");
  657.             (void) fflush (stderr);
  658.             }
  659.             return;
  660.         }
  661.         break;
  662.         case DVI_PUSH:
  663.         dvi_stackp -> stack_hh = hh;
  664.         dvi_stackp -> stack_vv = vv;
  665.         dvi_stackp -> stack_dvi = dvi_current;
  666.         dvi_stackp++;
  667.         break;
  668.         case DVI_POP:
  669.         dvi_stackp--;
  670.         hh = dvi_stackp -> stack_hh;
  671.         vv = dvi_stackp -> stack_vv;
  672.         dvi_current = dvi_stackp -> stack_dvi;
  673.         break;
  674.         case DVI_W0:
  675.         p = dvi_w;
  676.         goto move_right;
  677.         case DVI_X0:
  678.         p = dvi_x;
  679.         goto move_right;
  680.         case DVI_Y0:
  681.         p = dvi_y;
  682.         goto move_down;
  683.         case DVI_Z0:
  684.         p = dvi_z;
  685.         goto move_down;
  686.         case DVI_PRE:
  687.         error (1, 0, "unexpected PRE");
  688.         case DVI_POST:    /* shouldn't get this, reading backwards */
  689.         error (1, 0, "unexpected POST");
  690.         case DVI_POSTPOST:
  691.         error (1, 0, "unexpected POSTPOST");
  692.         default:
  693.         error (1, 0, "undefined DVI opcode (%d)", c);
  694.     }
  695.     }
  696. }
  697.